package io.renren.modules.generator.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import io.renren.common.utils.Constant;
import io.renren.common.utils.R;
import io.renren.common.utils.RedisKeys;
import io.renren.common.utils.RedisService;
import io.renren.common.vo.AddressImportVo;
import io.renren.common.vo.ProductAddressVo;
import io.renren.modules.generator.dao.AddressDao;
import io.renren.modules.generator.entity.*;
import io.renren.modules.generator.service.*;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.*;


@Service("addressService")
public class AddressServiceImpl extends ServiceImpl<AddressDao, AddressEntity> implements AddressService {

    @Autowired
    private  AddressDao addressDao;

    @Autowired
    private RedisService redisService;

    @Autowired
    private DtAreaService dtAreaService;

    @Autowired
    private DictionaryService dictionaryService;

    @Autowired
    private AddressCustomerService addressCustomerService;

    @Autowired
    private CustomerService customerService;

    @Override
    public List<AddressEntity> queryPage(Map<String, Object> params) {

        return addressDao.queryPage(params);
    }

    @Override
    public List<AddressEntity> queryToExcelExport(Map<String, Object> params) {

        return addressDao.queryToExcelExport(params);
    }

    @Override
    public int queryTotalToExcelExport(Map<String, Object> params) {
        return addressDao.queryTotalToExcelExport(params);
    }

    @Override
    public  int queryPageTotal(Map<String, Object> params) {

        return addressDao.queryPageTotal(params);
    }

    @Override
    public void updateStatusByIds(List<Integer> list) {
        addressDao.updateStatusByIds(list);
    }

    @Override
    public List<AddressEntity> queryAddressesByCustomerId(int id) {
        return addressDao.queryAddressesByCustomerId(id);
    }


    @Override
    public Map<String,List<AddressEntity>> queryAddressByCustomerIdAndByAddressProperty(int customerId) {
        List<AddressEntity> addressFrom = addressDao.queryAddressByCustomerIdAndByAddressProperty(customerId, Constant.AddressProperty.FROM_ADDRESS.getProperty());

        List<AddressEntity> addressTo = addressDao.queryAddressByCustomerIdAndByAddressProperty(customerId, Constant.AddressProperty.TO_ADDRESS.getProperty());
        HashMap<String, List<AddressEntity>> map = new HashMap<>();
        map.put(Constant.AddressProperty.FROM_ADDRESS.getProperty(),addressFrom);
        map.put(Constant.AddressProperty.TO_ADDRESS.getProperty(),addressTo);
        return map;
    }

    @Override
    public AddressEntity info(Integer id) {
        return addressDao.queryById(id);
    }

    @Override
    public Map<String, List<AddressEntity>> queryAllFromAddressAndAllToAddress() {
        List<AddressEntity> fromAddress = addressDao.queryAddressByProperty(Constant.AddressProperty.FROM_ADDRESS.getProperty());
        List<AddressEntity> toAddress = addressDao.queryAddressByProperty(Constant.AddressProperty.TO_ADDRESS.getProperty());
        HashMap<String, List<AddressEntity>> map = new HashMap<>();
        map.put(Constant.AddressProperty.FROM_ADDRESS.getProperty(),fromAddress);
        map.put(Constant.AddressProperty.TO_ADDRESS.getProperty(),toAddress);
        return map;
    }

    @Override
    public AddressEntity queryByCode(String code) {
        return this.selectOne(new EntityWrapper<AddressEntity>().eq(StringUtils.isNotBlank(code),"code",code));
    }

    @Override
    public Set<AddressEntity> queryFromAddressEntityListByToAddressIdAndProductId(Integer toAddressId, Integer productId) {
        return addressDao.queryFromAddressEntityListByToAddressIdAndProductId(toAddressId,productId);

    }

    /**
     * 地址导入逻辑：
     *  定义一个vo: AddressImportEntity
     *  遍历excel进行校验，封装此vo
     *  开始保存addressEntity和客户的关系
     *      1、判断addressCode是否在redis中：
     *          （1）如果存在：直接取出，得到AddressId,保存客户和地址的关系
     *          （2）如果不存在：查询数据库
     *                  a、如果数据库中有：取出addressEntity，得到addressId，保存客户和地址的关系；
     *                  b、如果数据库中没有：保存addressEntity，存入redis中，再保存客户与地址的关系；
     * @param book
     * @return
     */
    @Override
    @Transactional
    public R importFile(Workbook book) {
        Sheet sheet = book.getSheetAt(0);

        Integer fromAddressId = null;
        Integer toAddressId = null;
        Integer centerAddress=null;
        List<DictionaryEntity> dictionaryEntities = dictionaryEntities = dictionaryService.queryByType(Constant.ADDRESS_PROPERTY);;


        for (DictionaryEntity dictionaryEntity: dictionaryEntities) {
            String code = dictionaryEntity.getCode();
            if(code.equals(Constant.AddressProperty.FROM_ADDRESS.getProperty())){
                fromAddressId = dictionaryEntity.getId();
            }else if(code.equals(Constant.AddressProperty.TO_ADDRESS.getProperty())){
                toAddressId = dictionaryEntity.getId();
            }else{
                centerAddress = dictionaryEntity.getId();
            }
        }

        List<AddressImportVo> addressImportVos = new ArrayList<>();

        for (int i = 1; i <= sheet.getLastRowNum(); i++) {


            List<Integer> addressPropertyIds = new ArrayList<>();

            Row row = sheet.getRow(i);
            AddressImportVo addressImportVo = new AddressImportVo();
            AddressEntity addressEntity = new AddressEntity();
            AddressCustomerEntity addressCustomerEntity = new AddressCustomerEntity();

            /**
             * 客户代码
             */

            if(row.getCell(0) != null && !row.getCell(0).toString().trim().equals("")){
                row.getCell(0).setCellType(Cell.CELL_TYPE_STRING);
                String customerCode =  row.getCell(0).getStringCellValue().trim();
                if(customerCode.equals("end")){
                    break;
                }
                CustomerEntity customerEntity=null;
                String customerKey = RedisKeys.getCustomerKey(customerCode);
                Object o = redisService.get(customerKey);

                if(o != null){
                    customerEntity=(CustomerEntity) o;
                }else{
                    customerEntity = customerService.queryEntityByCode(customerCode);
                    if(customerEntity != null){
                        redisService.set(customerKey,customerEntity, Constant.getRedisKeyExpireTimeHoursToSecond(2));
                    }else{
                        return R.error("第"+i+"行客户没有维护，请先维护");
                    }
                }

                addressImportVo.setCustomerId(customerEntity.getId());
                addressImportVo.setCustomerCode(customerCode);

            }


            /**
             * 地址代码
             */
            if(row.getCell(2) != null && !row.getCell(2).toString().trim().equals("")){
                row.getCell(2).setCellType(Cell.CELL_TYPE_STRING);
                String addressCode =  row.getCell(2).getStringCellValue().trim();
                addressEntity.setCode(addressCode);

            }else{
                return R.error("第"+i+"行地址代码不能为空");
            }
            /**
             * 地址名称
             */
            if(row.getCell(3) != null && !row.getCell(3).toString().trim().equals("")){
                row.getCell(3).setCellType(Cell.CELL_TYPE_STRING);
                String addressName =  row.getCell(3).getStringCellValue().trim();

                addressEntity.setName(addressName);

            }else{
                return R.error("第"+i+"行地址名称不能为空");
            }

            /**
             * 城市代码缩写
             */
            if(row.getCell(4) != null && !row.getCell(4).toString().trim().equals("")){
                row.getCell(4).setCellType(Cell.CELL_TYPE_STRING);
                String dtAreaOmsMnemonicCode =  row.getCell(4).getStringCellValue().trim();
                String dtAreaOmsMnemonicCodeKey = RedisKeys.getDtAreaOmsMnemonicCodeKey(dtAreaOmsMnemonicCode);
                Object o = redisService.get(dtAreaOmsMnemonicCodeKey);
                DtAreaEntity dtAreaEntity = null;
                if(o != null){
                    dtAreaEntity = (DtAreaEntity) o;
                }else{
                    dtAreaEntity = dtAreaService.queryEntityByOmsMnemonicCode(dtAreaOmsMnemonicCode);
                    if(dtAreaEntity != null){
                        redisService.set(dtAreaOmsMnemonicCodeKey,dtAreaEntity, Constant.getRedisKeyExpireTimeMinutesToSecond(10));
                    }else{
                        return R.error("第"+i+"行城市代码["+dtAreaOmsMnemonicCode+"]没有维护在行政区域中，请先维护");
                    }
                }
                addressEntity.setDtAreaId(dtAreaEntity.getId());
                addressEntity.setDtAreaName(dtAreaEntity.getAreaName());
                addressEntity.setDtAreaOmsMnemonicCode(dtAreaEntity.getOmsMnemonicCode());
            }else{
                return R.error("第"+i+"行城市代码不能为空");
            }

            /**
             * 省
             */
            if(row.getCell(5) != null && !row.getCell(5).toString().trim().equals("")){
                row.getCell(5).setCellType(Cell.CELL_TYPE_STRING);
                String province =  row.getCell(5).getStringCellValue().trim();
                String provinceKey = RedisKeys.getDtAreaProvince(province);
                Object o = redisService.get(provinceKey);
                DtAreaEntity dtAreaEntity = null;
                if(o != null){
                    dtAreaEntity = (DtAreaEntity) o;
                }else{
                    dtAreaEntity = dtAreaService.queryEntutyByAreaNameAndLevel(province,1);

                    if(dtAreaEntity != null){
                        redisService.set(provinceKey,dtAreaEntity, Constant.getRedisKeyExpireTimeMinutesToSecond(10));
                    }else{
                        return R.error("第"+i+"行省名称["+province+"]没有维护在行政区域中，请先维护");
                    }
                }
                addressEntity.setProvince(province);
                addressEntity.setProvinceCode(dtAreaEntity.getId().toString());
            }else{
                return R.error("第"+i+"行省不能为空");
            }

            /**
             * 市
             */
            if(row.getCell(6) != null && !row.getCell(6).toString().trim().equals("")){
                row.getCell(6).setCellType(Cell.CELL_TYPE_STRING);
                String city =  row.getCell(6).getStringCellValue().trim();
                String cityKey = RedisKeys.getDtAreaCity(city);
                Object o = redisService.get(cityKey);
                DtAreaEntity dtAreaEntity = null;
                if(o != null){
                    dtAreaEntity = (DtAreaEntity) o;
                }else{
                    dtAreaEntity = dtAreaService.queryEntutyByAreaNameAndLevel(city,2);

                    if(dtAreaEntity != null){
                        redisService.set(cityKey,dtAreaEntity, Constant.getRedisKeyExpireTimeMinutesToSecond(10));
                    }else{
                        return R.error("第"+i+"行市名称["+city+"]没有维护在行政区域中，请先维护");
                    }
                }
                addressEntity.setCity(city);
                addressEntity.setCityCode(dtAreaEntity.getId().toString());
            }

            /**
             * 区
             */
            if(row.getCell(7) != null && !row.getCell(7).toString().trim().equals("")){
                row.getCell(7).setCellType(Cell.CELL_TYPE_STRING);
                String area =  row.getCell(7).getStringCellValue().trim();
                String areaKey = RedisKeys.getDtAreaArea(area);
                Object o = redisService.get(areaKey);
                DtAreaEntity dtAreaEntity = null;
                if(o != null){
                    dtAreaEntity = (DtAreaEntity) o;
                }else{
                    dtAreaEntity = dtAreaService.queryEntutyByAreaNameAndLevel(area,3);

                    if(dtAreaEntity != null){
                        redisService.set(areaKey,dtAreaEntity, Constant.getRedisKeyExpireTimeMinutesToSecond(10));
                    }else{
                        return R.error("第"+i+"行区名称["+area+"]没有维护在行政区域中，请先维护");
                    }
                }
                addressEntity.setArea(area);
                addressEntity.setAreaCode(dtAreaEntity.getId().toString());
            }

            /**
             * 详细地址
             */
            if(row.getCell(8) != null && !row.getCell(8).toString().trim().equals("")){
                row.getCell(8).setCellType(Cell.CELL_TYPE_STRING);
                String detailedAddress =  row.getCell(8).getStringCellValue().trim();

                addressEntity.setDetailedAddress(detailedAddress);
            }

            /**
             * 联系人
             */
            if(row.getCell(9) != null && !row.getCell(9).toString().trim().equals("")){
                row.getCell(9).setCellType(Cell.CELL_TYPE_STRING);
                String linkman =  row.getCell(9).getStringCellValue().trim();

                addressEntity.setLinkMan(linkman);
            }

            /**
             * 手机
             */
            if(row.getCell(10) != null && !row.getCell(10).toString().trim().equals("")){
                row.getCell(10).setCellType(Cell.CELL_TYPE_STRING);
                String phone =  row.getCell(10).getStringCellValue().trim();

                addressEntity.setLinkManPhone(phone);
            }

            /**
             * 电话
             */
            if(row.getCell(11) != null && !row.getCell(11).toString().trim().equals("")){
                row.getCell(11).setCellType(Cell.CELL_TYPE_STRING);
                String tel =  row.getCell(11).getStringCellValue().trim();

                addressEntity.setLinkManTelement(tel);
            }

            /**
             * 邮箱
             */

            if(row.getCell(12) != null && !row.getCell(12).toString().trim().equals("")){
                row.getCell(12).setCellType(Cell.CELL_TYPE_STRING);
                String eamil =  row.getCell(12).getStringCellValue().trim();

                addressEntity.setLinkManEmail(eamil);
            }



            /**
             * 提货点
             */

            if(row.getCell(13) != null && !row.getCell(13).toString().trim().equals("")){
                row.getCell(13).setCellType(Cell.CELL_TYPE_STRING);
                String from =  row.getCell(13).getStringCellValue().trim();
                if("Y".equals(from)){
                    addressPropertyIds.add(fromAddressId);
                }

            }

            /**
             * 送货点
             */

            if(row.getCell(14) != null && !row.getCell(14).toString().trim().equals("")){
                row.getCell(14).setCellType(Cell.CELL_TYPE_STRING);
                String to =  row.getCell(14).getStringCellValue().trim();

                if("Y".equals(to)){
                    addressPropertyIds.add(toAddressId);
                }
            }

            /**
             * 中转点
             */


            if(row.getCell(15) != null && !row.getCell(15).toString().trim().equals("")){
                row.getCell(15).setCellType(Cell.CELL_TYPE_STRING);
                String center =  row.getCell(15).getStringCellValue().trim();

               if("Y".equals(center)){
                   addressPropertyIds.add(centerAddress);
               }
            }

            addressEntity.setAddressPropertyDictionaryIds(StringUtils.join(addressPropertyIds,","));

            /**
             * 地址类型
             */
            if(row.getCell(17) != null && !row.getCell(17).toString().trim().equals("")){
                row.getCell(17).setCellType(Cell.CELL_TYPE_STRING);
                String addressType =  row.getCell(17).getStringCellValue().trim();
                addressEntity.setAddressTypeDictionaryId(Integer.valueOf(addressType));
            }

            /**
             * 备注
             */
            if(row.getCell(18) != null && !row.getCell(18).toString().trim().equals("")){
                row.getCell(18).setCellType(Cell.CELL_TYPE_STRING);
                String remark =  row.getCell(18).getStringCellValue().trim();
                addressEntity.setRemark(remark);
            }

            /**
             * 预留字段1
             */
            if(row.getCell(19) != null && !row.getCell(19).toString().trim().equals("")){
                row.getCell(19).setCellType(Cell.CELL_TYPE_STRING);
                String extendFirst =  row.getCell(19).getStringCellValue().trim();
                addressEntity.setExtendFirst(extendFirst);
            }
            /**
             * 预留字段2
             */
            if(row.getCell(20) != null && !row.getCell(20).toString().trim().equals("")){
                row.getCell(20).setCellType(Cell.CELL_TYPE_STRING);
                String extendSecond =  row.getCell(20).getStringCellValue().trim();
                addressEntity.setExtendSecond(extendSecond);
            }

            /**
             * 预留字段3
             */
            if(row.getCell(21) != null && !row.getCell(21).toString().trim().equals("")){
                row.getCell(21).setCellType(Cell.CELL_TYPE_STRING);
                String extendThird =  row.getCell(21).getStringCellValue().trim();
                addressEntity.setExtendThird(extendThird);
            }

            addressImportVo.setAddressEntity(addressEntity);

            addressImportVos.add(addressImportVo);

        }

        String customerCode ="";
        String addressCode="";


        try {
            if(addressImportVos.size() >0){
                for (AddressImportVo addressImportVo:addressImportVos) {
                    AddressEntity addressEntity = addressImportVo.getAddressEntity();
                    addressCode = addressEntity.getCode();
                    customerCode = addressImportVo.getCustomerCode();
                    String addressEntityCode = addressEntity.getCode();
                    String addressKey = RedisKeys.getAddressKey(addressEntityCode);
                    Object o = redisService.get(addressKey);
                    AddressEntity entity =null;
                    if(o != null){
                        entity = (AddressEntity) o;
                    }else{
                        entity = queryByCode(addressEntityCode);
                        if(entity == null){
                            this.insert(addressEntity);
                            entity = addressEntity;
                            redisService.set(addressKey,addressEntity,Constant.getRedisKeyExpireTimeMinutesToSecond(10));
                        }
                    }

                    if(addressImportVo.getCustomerId() != null){
                        AddressCustomerEntity addressCustomerEntity = new AddressCustomerEntity();
                        addressCustomerEntity.setCustomerId(addressImportVo.getCustomerId());
                        addressCustomerEntity.setAddressId(entity.getId());
                        addressCustomerService.insert(addressCustomerEntity);
                    }


                }

            }
        }catch (DuplicateKeyException d){
            d.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new DuplicateKeyException("客户代码["+customerCode+"]和地址代码[ "+addressCode+" ]的关系已经维护,请不要重复导入");
        }catch (Exception e){
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }

        return R.ok();
    }

    @Override
    public void save(AddressEntity address) {
        saveOrUpdateCustomer(address.getCustomerIds(),address.getId());
        this.insert(address);
        redisService.removePattern(RedisKeys.getCustomerAddresskey("*"));
        redisService.remove(RedisKeys.getAddressKey(address.getName()));
    }

    @Override
    public void update(AddressEntity address) {
        saveOrUpdateCustomer(address.getCustomerIds(),address.getId());
        this.updateById(address);
        redisService.removePattern(RedisKeys.getAddressKey("*"));
        redisService.removePattern(RedisKeys.getCustomerAddresskey("*"));
    }

    @Override
    public List<AddressEntity> queryEntityListByCode(String code, String type, Integer customerId) {
        return addressDao.queryEntityListByCode(code,type,customerId);
    }



    @Override
    public List<ProductAddressVo> queryToAddressByToAddressNameAndProductId(String addressName, Integer productId) {
        return addressDao.queryToAddressByToAddressNameAndProductId(addressName,productId);
    }


    private void saveOrUpdateCustomer(List<Integer> customerIds,Integer addressId){
        Map<String, Object> map = new HashMap<>();
        map.put("address_id",addressId);
        addressCustomerService.deleteByMap(map);
        for (int i = 0; i <customerIds.size(); i++) {
            AddressCustomerEntity addressCustomerEntity = new AddressCustomerEntity();
            addressCustomerEntity.setCustomerId(customerIds.get(i));
            addressCustomerEntity.setAddressId(addressId);
            addressCustomerService.insert(addressCustomerEntity);
        }

    }


}
